/**
 * @author: 團長
 * @date: 2013-6-3-上午11:51:14
 */
package net.loyintean.pearlshell.base.model.impl;

import net.loyintean.pearlshell.base.model.ILogInfo;

// DONE 团长 2014-4-9 to团长 to reduce incorrectly usage, mark this class as deprecated.
/** 为日志做字符串操作。日志字符串按如下格式：标识信息+区分符号+内容信息。例如：LogInfoTest#testBuildLogInfi()@:error-
 * nullpointerexception中，
 * LogInfoTest#testBuildLogInfi()@是标识信息；:是区分符号；error-nullpointerexception是内容信息
 * <p>
 * 标识信息：用来定位日志位置的信息。例如：类名，方法名，参数数据等。<br>
 * 鉴于类名、方法名会由日志自行记录，建议这里的标志信息记录相关参数数据即可。
 * <p>
 * 区分符号：用于分割标识信息和内容信息，并用作此类中某些方法的位置标识。<br>
 * 默认情况下，以“:”（英文冒号）区分日志标识信息和日志内容。 可以通过构造方法设定这个区分符号。<br>
 * 但无论使用默认的还是自定义的，区分符号能且只能出现一次 。
 * <p>
 * 内容信息：用于记录日志输出内容的信息。例如：异常类、异常信息、异常堆栈；或者操作结果；或者中间变量的取值。
 * <p>
 * 2014-1-3 团长 add five log methods. v1.1.0
 * <p>
 * 2014-4-8 Loy abstract an interface and factory, deprecated a constructor.
 * v2.0.0
 * <p>
 * 2014-4-9 Loy fix review. v2.0.1
 * <p>
 * 2014-12-21 jun.lin add two methods {@link #start(String)} and {@link #end()}.
 * v3.0.0
 * 
 * @author 團長
 * @since 2014-12-21
 * @version 3.0.0 */
class LogInfoModel implements ILogInfo {

	/** 用来生成日志信息
	 * 
	 * @author 團長
	 * @since 2013-6-3 */
	private StringBuilder logInfo;

	/** 日志标识信息和日志内容信息的区分点
	 * 
	 * @author 團長
	 * @since 2013-6-3 */
	private int logInfoPrefix;

	/** 指定日志标识信息，并以默认的区分符号（“:”）来区分标识信息和后续的内容信息。
	 * <p>
	 * 调用此方法时，建议":"出现在tagInfo的最后一位。如果没有出现":"，将在最后一位追加一个":"。
	 * 如果":"出现在此前的位置上，则在调用log(String)方法时，":"后面的字段将被截断
	 * <p>
	 * 2014-11-13 jun.lin 增加默认的logInfo长度设置：设定为入参tagInfo的三倍长。
	 * 
	 * @author 團長
	 * @since 2014-11-13
	 * @param tagInfo
	 *            日志“桩”信息，可用来在多线程环境下区分哪些日志是同一线程产生的。 */
	LogInfoModel(String tagInfo) {
		logInfo = new StringBuilder(tagInfo.length() * 3);
		logInfo.append(tagInfo);
		markLogInfoPrefix(":");
	}

	/** 指定日志标识信息，并以自定义的的区分符号（preFix）来区分标识信息和后续的内容信息
	 * <p>
	 * 调用此方法时，建议preFix出现在tagInfo的最后一位。如果没有出现，将在最后一位追加一个preFix。
	 * 如果preFix出现在此前的位置上，则在调用log(String)方法时，preFix后面的字段将被截断
	 * 
	 * @author 團長
	 * @since 2013-6-3
	 * @param tagInfo
	 * @param preFix */
	public LogInfoModel(String tagInfo, String preFix) {
		// 记录标识信息
		logInfo = new StringBuilder(tagInfo);
		markLogInfoPrefix(preFix);
	}

	/** 检查logInfo中的区分符号是否存在，如果不存在则在其末尾进行追加。然后记录其位置
	 * 
	 * @author 團長
	 * @since 2013-6-3
	 * @param preFix */
	private void markLogInfoPrefix(String preFix) {
		// 追加区分符号
		if (logInfo.indexOf(preFix) < 0) {
			logInfo.append(preFix);
		}

		logInfoPrefix = logInfo.indexOf(preFix) + preFix.length();
	}

	// DONE 团长 2014-4-9 to团长 reduce visibility of this method.
	// currently it's impossible, as this method is reference by many other
	// class.
	// however, it's a good idea to deprecated it.
	/** 在标识信息和区分符号后追加日志内容信息
	 * <p>
	 * 2014-4-9 Loy this method should only used in this class.
	 * <p>
	 * 2014-12-21 jun.lin set this method as private
	 * 
	 * @author 團長
	 * @since 2014-12-21
	 * @param log
	 *            日志内容信息
	 * @return 标识信息+区分符号+指定内容信息的完整的日志信息 */
	private String log(String log) {
		// replace会有一个expandCapacity（隐含Arrays.copy）操作和一个System.arraycopy操作。
		// done 考虑是否有更高效的方式？
		// 在初始化时有一个三倍初始化空间的操作。希望能有点优化作用。
		return logInfo.replace(logInfoPrefix, logInfo.length(), log).toString();
	}

	/** record the start log in format of "'stub infomation' start!'"
	 * 
	 * @author 團長
	 * @since 2014-1-3
	 * @return */
	@Override
	public String start() {
		return this.log("start!");
	}

	/** 输出带参数的起始日志
	 * 
	 * @see net.loyintean.pearlshell.base.model.
	 *      ILogInfo#start(java.lang.String) */
	@Override
	public String start(String log) {
		return this.log("start! - " + log);
	}

	/** 输出不带参数的结束日志
	 * 
	 * @see net.loyintean.pearlshell.base.model.ILogInfo#end() */
	@Override
	public String end() {
		return this.log("end!");
	}

	/** record the end log in format of "'stub infomation' end! - 'log'"
	 * 
	 * @author 團長
	 * @since 2014-1-3
	 * @param log
	 *            log message
	 * @return log string in format */
	@Override
	public String end(String log) {
		return this.log("end! - " + log);
	}

	/** record the inner log in format of "'stub infomation' inner - 'log'"
	 * 
	 * @author 團長
	 * @since 2014-1-3
	 * @param log
	 *            log message
	 * @return log string in format */
	@Override
	public String inner(String log) {
		return this.log("inner - " + log);
	}

	/** record the error log in format of "'stub infomation' error - 'log'"
	 * 
	 * @author 團長
	 * @since 2014-1-3
	 * @param log
	 *            log message
	 * @return log string in format */
	@Override
	public String error(String log) {
		return this.log("error - " + log);
	}

	/** record the error log in format of
	 * "'stub infomation' error - &e='e'&e.getMessage='e.getMessage()'"
	 * 
	 * @author 團長
	 * @since 2014-1-3
	 * @param e
	 *            exception to log
	 * @return log string in format */
	@Override
	public String error(Throwable e) {
		return this.log("error - &e=" + e + "&e.getMessage=" + e.getMessage());
	}

	/** 字符串输出方法。将当前的logInfo内容输出
	 * 
	 * @author 團長
	 * @since 2013-6-3
	 * @return
	 * @see java.lang.Object#toString() */
	@Override
	public String toString() {
		// DONE 团长 2014-4-9 to团长 use method #log()
		// to guarantee output only stub.
		return this.log("");
	}

}